package wechat

import (
	"bytes"
	"crypto/aes"
	"crypto/cipher"
	"encoding/base64"
	"encoding/json"
	"errors"
	"gin-cli/utils/network"
	"strconv"
	"strings"
)

/**
* Title: 微信小程序通过登录code换取sessionKey/openid/unionid
* Author: lauwen
* E-mail: me@luxuewen.com
 */
func Code2Session (code, app_id, app_secret string) (map[string]interface{}, error)  {
	url := "https://api.weixin.qq.com/sns/jscode2session?appid=" + app_id + "&secret=" + app_secret + "&js_code=" + code + "&grant_type=authorization_code"

	resp := network.HttpGet(url)
	respByte := []byte(resp)

	var response map [string] interface{}
	err := json.Unmarshal(respByte, &response)

	if response["errcode"] != nil && response["errmsg"] != nil {
		var buffer bytes.Buffer
		buffer.WriteString(strconv.FormatFloat(float64(response["errcode"].(float64)), 'f', 0, 64))
		buffer.WriteString(":")
		buffer.WriteString(response["errmsg"].(string))

		return nil, errors.New(buffer.String())
	}

	return response, err
}

/**
* Title: 获取微信小程序accessToken
* Author: lauwen
* E-mail: me@luxuewen.com
 */
func GetAccessToken (app_id, app_secret string) (map[string]interface{}, error)  {
	url := "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + app_id + "&secret=" + app_secret

	resp := network.HttpGet(url)
	respByte := []byte(resp)

	var response map [string] interface{}
	err := json.Unmarshal(respByte, &response)

	if response["errcode"] != nil && response["errmsg"] != nil {
		var buffer bytes.Buffer
		buffer.WriteString(strconv.FormatFloat(float64(response["errcode"].(float64)), 'f', 0, 64))
		buffer.WriteString(":")
		buffer.WriteString(response["errmsg"].(string))

		return nil, errors.New(buffer.String())
	}

	return response, err
}

/**
* Title: 微信小程序用户数据解密算法
* Author: lauwen
* E-mail: me@luxuewen.com
 */
func DecryptData (app_id, session_key, iv, encrypted_data string) (map[string]interface{}, error) {
	if len := strings.Count(session_key, "") - 1; len != 24 {
		return nil, errors.New("Invalid value session_key!")
	}
	aesKey, err := base64.StdEncoding.DecodeString(session_key)
	if err != nil {
		return nil, err
	}

	if len := strings.Count(iv, "") - 1; len != 24 {
		return nil, errors.New("Invalid value iv!")
	}
	ivKey, err := base64.StdEncoding.DecodeString(iv)
	if err != nil {
		return nil, err
	}

	decodeData, err := base64.StdEncoding.DecodeString(encrypted_data)
	if err != nil {
		return nil, err
	}

	dataBytes, err := AesDecrypt(decodeData, aesKey, ivKey)
	if err != nil {
		return nil, err
	}

	var result map [string] interface{}
	err = json.Unmarshal(dataBytes, &result)
	if err != nil {
		return nil, err
	}

	watermark := result["watermark"].(map[string]interface{})
	if watermark["appid"] != app_id {
		return nil, errors.New("Invalid appid data!")
	}

	return result, err
}

/**
* Title: 微信解密相关aes解密算法
* Author: lauwen
* E-mail: me@luxuewen.com
 */
func AesDecrypt(crypted, key, iv []byte) ([]byte, error) {
	block, err := aes.NewCipher(key)
	if err != nil {
		return nil, err
	}

	blockMode := cipher.NewCBCDecrypter(block, iv)
	origData := make([]byte, len(crypted))
	blockMode.CryptBlocks(origData, crypted)
	//获取的数据尾端占位符,去除它
	length := len(origData)
	unp := int(origData[length-1])
	data := origData[:(length - unp)]
	return data, nil
}


